提交 d3b2f4da 编写于 作者: M MaxKey

SocialSignOn

上级 ba518828
......@@ -56,8 +56,8 @@ xmlbeansVersion =5.0.2
commonscompressVersion =1.20
log4jVersion =2.17.1
kafkaclientsVersion =2.8.1
rocketmqclientVersion =4.9.2
rocketmqspringbootVersion =2.2.1
rocketmqclientVersion =4.9.3
rocketmqspringbootVersion =2.2.2
poiVersion =5.1.0
tomcatVersion =9.0.62
tomcatembedloggingjuliVersion =8.5.2
......@@ -117,7 +117,7 @@ jakartavalidationapiVersion =3.0.0
attoparserVersion =2.0.5.RELEASE
unbescapeVersion =1.1.6.RELEASE
slf4jVersion =1.7.35
jacksonVersion =2.13.1
jacksonVersion =2.13.2
woodstoxVersion =6.2.8
bouncycastleVersion =1.69
junitVersion =4.11
......
......@@ -39,6 +39,7 @@ public class AuthJwt implements Serializable {
private String email;
private String instId;
private String instName;
private int passwordSetType;
private List<String> authorities;
......@@ -147,6 +148,15 @@ public class AuthJwt implements Serializable {
public void setTicket(String ticket) {
this.ticket = ticket;
}
public int getPasswordSetType() {
return passwordSetType;
}
public void setPasswordSetType(int passwordSetType) {
this.passwordSetType = passwordSetType;
}
@Override
public String toString() {
......
......@@ -23,6 +23,7 @@ package org.maxkey.authn.support.socialsignon;
import javax.servlet.http.HttpServletRequest;
import org.maxkey.authn.LoginCredential;
import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.authn.jwt.AuthJwt;
import org.maxkey.authn.web.AuthorizationUtils;
import org.maxkey.constants.ConstsLoginType;
......@@ -87,16 +88,15 @@ public class SocialSignOnEndpoint extends AbstractSocialSignOnEndpoint{
}
@RequestMapping(value={"/bind/{provider}"}, method = RequestMethod.POST)
public ResponseEntity<?> bind(@PathVariable String provider) {
@RequestMapping(value={"/bind/{provider}"}, method = RequestMethod.GET)
public ResponseEntity<?> bind(@PathVariable String provider,@CurrentUser UserInfo userInfo) {
//auth call back may exception
try {
String instId = WebContext.getInst().getId();
SocialsAssociate socialsAssociate = this.authCallback(instId,provider);
UserInfo userInfo = AuthorizationUtils.getUserInfo();
SocialsAssociate socialsAssociate = this.authCallback(userInfo.getInstId(),provider);
socialsAssociate.setSocialUserInfo(accountJsonString);
socialsAssociate.setUserId(userInfo.getId());
socialsAssociate.setUsername(userInfo.getUsername());
socialsAssociate.setInstId(userInfo.getInstId());
//socialsAssociate.setAccessToken(JsonUtils.object2Json(accessToken));
//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
_logger.debug("Social Bind : "+socialsAssociate);
......
......@@ -11,6 +11,7 @@
a.id,
a.userid,
a.username,
a.socialuserid,
a.createdDate,
a.updatedDate
from
......@@ -18,12 +19,12 @@
left join
mxk_socials_associate a
on a.provider = p.provider and a.userid = #{id}
on a.provider = p.provider
and a.instid = p.instid
and a.instid = #{instId}
and a.userid = #{id}
where
a.instid = p.instid
and a.instid = #{instId}
and p.status =1
p.status =1
order by p.sortindex
</select>
......
......@@ -20,16 +20,7 @@ import { LayoutDefaultOptions } from '../../theme/layout-default';
<layout-default-header-item direction="left">
<a href="#">
<img src="../assets/logo.jpg" alt="logo" style="height: 50px;height: 50px;float: left;" />
<div
style="letter-spacing: 2px;
font-size: 20px;
font-weight: bolder;
color:white;
width: 450px;
margin-top: 12px;"
>
Max<span style="color: #FFD700;">Key</span>{{ 'mxk.title' | i18n }}
</div>
<div class="alain-default__header-title"> Max<span style="color: #FFD700;">Key</span>{{ 'mxk.title' | i18n }} </div>
</a>
</layout-default-header-item>
......
......@@ -40,9 +40,17 @@
</td>
<td nzAlign="left" nzBreakWord="false"
><div nz-col>
<button nz-button type="button" [nzType]="'primary'" style="float: left">{{ 'mxk.text.edit' | i18n }}</button>
<button nz-button type="button" (click)="onDelete($event, data.id)" [nzType]="'primary'" nzDanger>{{
'mxk.text.delete' | i18n
<button
*ngIf="data.updatedDate === null"
nz-button
type="button"
(click)="onAdd($event, data.provider)"
[nzType]="'primary'"
style="float: left"
>{{ 'mxk.socialsassociate.text.bind' | i18n }}</button
>
<button *ngIf="data.updatedDate" nz-button type="button" (click)="onDelete($event, data.id)" [nzType]="'primary'" nzDanger>{{
'mxk.socialsassociate.text.unbind' | i18n
}}</button></div
></td
>
......
......@@ -6,10 +6,14 @@ import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { logging } from 'protractor';
import { SocialsAssociateService } from '../../../service/socials-associate.service';
import { SocialsProviderService } from '../../../service/socials-provider.service';
import { set2String } from '../../../shared/index';
import { log } from 'console';
@Component({
selector: 'app-socials-associate',
templateUrl: './socials-associate.component.html',
......@@ -66,6 +70,7 @@ export class SocialsAssociateComponent implements OnInit {
constructor(
private modalService: NzModalService,
private socialsProviderService: SocialsProviderService,
private socialsAssociateService: SocialsAssociateService,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder,
......@@ -89,22 +94,11 @@ export class SocialsAssociateComponent implements OnInit {
onReset(): void { }
onAdd(e: MouseEvent): void {
onAdd(e: MouseEvent, provider: string): void {
e.preventDefault();
const modal = this.modalService.create({
//nzContent: SocialsProviderEditerComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: false,
id: ''
},
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
this.socialsProviderService.authorize(provider).subscribe(res => {
//console.log(res.data);
window.location.href = res.data;
});
}
......@@ -135,6 +129,7 @@ export class SocialsAssociateComponent implements OnInit {
this.query.params.startDate = '';
}
this.socialsAssociateService.fetch(this.query.params).subscribe(res => {
console.log(res.data);
this.query.results.rows = res.data;
this.query.submitLoading = false;
this.query.tableLoading = false;
......
import { Inject, Optional, Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { ReuseTabService } from '@delon/abc/reuse-tab';
import { SettingsService } from '@delon/theme';
......@@ -14,8 +14,9 @@ export class CallbackComponent implements OnInit {
provider = '';
constructor(
private router: Router,
private socialsProviderService: SocialsProviderService,
private settingsSrv: SettingsService,
private settingsService: SettingsService,
private authenticationService: AuthenticationService,
@Optional()
@Inject(ReuseTabService)
......@@ -25,14 +26,22 @@ export class CallbackComponent implements OnInit {
ngOnInit(): void {
this.provider = this.route.snapshot.params['provider'];
this.socialsProviderService.callback(this.provider, this.route.snapshot.queryParams).subscribe(res => {
if (res.code === 0) {
// 清空路由复用信息
this.reuseTabService.clear();
// 设置用户Token信息
this.authenticationService.auth(res.data);
}
this.authenticationService.navigate({});
});
if (!this.settingsService.user.name) {
this.socialsProviderService.callback(this.provider, this.route.snapshot.queryParams).subscribe(res => {
if (res.code === 0) {
// 清空路由复用信息
this.reuseTabService.clear();
// 设置用户Token信息
this.authenticationService.auth(res.data);
}
this.authenticationService.navigate({});
});
} else {
this.socialsProviderService.bind(this.provider, this.route.snapshot.queryParams).subscribe(res => {
if (res.code === 0) {
}
this.router.navigateByUrl('/config/socialsassociate');
});
}
}
}
......@@ -260,6 +260,7 @@ export class UserLoginComponent implements OnInit, OnDestroy {
}
getQrCode(): void {
this.authenticationService.clearUser();
this.socialsProviderService.scanqrcode(this.socials.qrScan).subscribe(res => {
if (res.code === 0) {
if (this.socials.qrScan === 'workweixin') {
......
......@@ -49,6 +49,11 @@ export class AuthenticationService {
this.tokenService.clear();
}
clearUser() {
let user: User = {};
this.settingsService.setUser(user);
}
auth(authJwt: any) {
let user: User = {
name: `${authJwt.displayName}(${authJwt.username})`,
......@@ -56,7 +61,8 @@ export class AuthenticationService {
username: authJwt.username,
userId: authJwt.id,
avatar: './assets/img/avatar.svg',
email: authJwt.email
email: authJwt.email,
passwordSetType: authJwt.passwordSetType
};
let hostnames = window.location.hostname.split('.');
......
......@@ -26,4 +26,8 @@ export class SocialsProviderService extends BaseService<SocialsProvider> {
callback(provider: string, params: NzSafeAny): Observable<Message<SocialsProvider>> {
return this.getByParams(params, `/logon/oauth20/callback/${provider}?_allow_anonymous=true`);
}
bind(provider: string, params: NzSafeAny): Observable<Message<SocialsProvider>> {
return this.getByParams(params, `/logon/oauth20/bind/${provider}?_allow_anonymous=true`);
}
}
......@@ -2,7 +2,7 @@
<ul nz-menu nzMode="horizontal" nzTheme="dark" style="text-align: center">
<!--一级菜单-->
<ng-container *ngFor="let mnav of ls">
<li nz-menu-item *ngIf="mnav.children.length == 0">
<li nz-menu-item *ngIf="mnav.children.length == 0" style="min-width: 80px">
<a href="#{{ mnav.link }}">{{ mnav.text }}</a>
</li>
<li nz-submenu nzTitle="{{ mnav.text }}" *ngIf="mnav.children.length > 0">
......
......@@ -18,7 +18,7 @@ import { LayoutDefaultOptions } from './types';
<div class="alain-default__progress-bar" *ngIf="isFetching"></div>
<layout-default-header [options]="options" [items]="headerItems"></layout-default-header>
<!--menu-->
<div id="mainMenu" nzTheme="dark" style="background: #001529;">
<div id="mainMenu" nzTheme="dark" style="background: #001529;" class="alain-default__fixed">
<!--<ng-container *ngTemplateOutlet="asideUser"></ng-container>-->
<ng-container *ngTemplateOutlet="nav"></ng-container>
<layout-default-nav *ngIf="!nav" class="d-block" style="margin-top: 64px; width:80%"></layout-default-nav>
......
......@@ -9,6 +9,15 @@
background-color: @alain-default-header-bg;
box-shadow: @alain-default-header-box-shadow;
&-title {
width: 450px;
margin-top: 12px;
color:@alain-default-header-title;
font-weight: bolder;
font-size: 20px;
letter-spacing: 2px;
}
&-logo {
width: @alain-default-aside-wd;
margin-left: -@alain-default-header-padding;
......@@ -60,7 +69,7 @@
&-item,
nz-badge {
color: #fff;
color: black;
}
&-item {
......@@ -75,8 +84,8 @@
transition: background-color 300ms;
&:hover {
color: #fff;
background-color: rgb(255 255 255 / 20%) !important;
color: black;
background-color: rgb(188 181 181 / 20%) !important;
}
> i,
......
......@@ -2,6 +2,7 @@
@alain-default-header-bg: @component-background;
@alain-default-header-box-shadow: @shadow-1-down;
@alain-default-header-title:white;
@alain-default-aside-bg: @component-background;
@alain-default-aside-nav-selected-bg: @component-background;
......
......@@ -3,6 +3,7 @@
@alain-default-ease: cubic-bezier(0.25, 0, 0.15, 1);
@alain-default-header-hg: 64px;
@alain-default-header-bg: #fff;
@alain-default-header-title:black;
@alain-default-header-padding: @layout-gutter * 2;
@alain-default-header-search-enabled: true;
@alain-default-header-icon-fs: 18px;
......
......@@ -18,7 +18,7 @@
"text.username": "Username",
"text.mobile": "Mobile Number",
"text.password": "Password",
"text.captcha": "CAPTCHA",
"text.captcha": "Captcha",
"text.smscode": "Code"
},
"menu": {
......@@ -222,8 +222,10 @@
"icon": "Icon",
"provider": "Provider",
"providerName": "ProviderName",
"createdDate": "BindTime ",
"updatedDate": "LastLoginTime"
"createdDate": "BindTime",
"updatedDate": "LastLoginTime",
"text.bind": "Bind",
"text.unbind": "Unbind"
},
"password":{
"id": "Id",
......
......@@ -516,7 +516,9 @@
"provider": "供应商",
"providerName": "供应商名称",
"createdDate": "绑定时间",
"updatedDate": "最近登录时间"
"updatedDate": "最近登录时间",
"text.bind": "绑定账号",
"text.unbind": "解除绑定"
},
"password":{
"id": "用户编码",
......
......@@ -2,7 +2,7 @@
// - `default` Default theme
// - `dark` Import the official dark less style file
// - `compact` Import the official compact less style file
@import '@delon/theme/theme-default.less';
@import '../app/theme/layout-default/style/theme-default.less';
// ==========The following is the custom theme variable area==========
// The theme paraments can be generated at https://ng-alain.github.io/ng-alain/
......
<form nz-form [formGroup]="form" (ngSubmit)="submit()" role="form">
<nz-alert *ngIf="error" [nzType]="'error'" [nzMessage]="error" [nzShowIcon]="true" class="mb-lg"></nz-alert>
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="Please enter username">
<nz-form-control nzErrorTip="">
<nz-input-group nzSize="large" [nzAddOnBefore]="usernamePreffixIcon">
<input nz-input formControlName="userName" placeholder="{{ 'mxk.login.text.username' | i18n }}" style="font-weight: bold" />
</nz-input-group>
......@@ -11,7 +11,7 @@
</nz-form-control>
</nz-form-item>
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="Please enter password">
<nz-form-control nzErrorTip="">
<nz-input-group [nzSuffix]="suffixTemplate" nzSize="large" [nzAddOnBefore]="passwordPreffixIcon">
<input
[type]="passwordVisible ? 'text' : 'password'"
......@@ -30,26 +30,22 @@
</nz-form-control>
</nz-form-item>
<nz-form-item style="width: 100%">
<nz-form-control nzErrorTip="Please enter captcha">
<nz-row [nzGutter]="8">
<nz-col [nzSpan]="16">
<nz-input-group nzSearch nzSize="large" [nzAddOnBefore]="captchaPreffixIcon">
<input
style="font-weight: bold"
type="text"
formControlName="captcha"
nz-input
placeholder="{{ 'mxk.login.text.captcha' | i18n }}"
/>
</nz-input-group>
<ng-template #captchaPreffixIcon>
<i nz-icon nzType="lock" nzTheme="outline"></i>
</ng-template>
</nz-col>
<nz-col [nzSpan]="8">
<img src="{{ imageCaptcha }}" (click)="getImageCaptcha()" />
</nz-col>
</nz-row>
<nz-form-control nzErrorTip="">
<nz-input-group nzSearch nzSize="large" [nzAddOnBefore]="captchaPreffixIcon" nzSearch [nzAddOnAfter]="suffixImageCaptchaButton">
<input
style="font-weight: bold"
type="text"
formControlName="captcha"
nz-input
placeholder="{{ 'mxk.login.text.captcha' | i18n }}"
/>
</nz-input-group>
<ng-template #captchaPreffixIcon>
<i nz-icon nzType="lock" nzTheme="outline"></i>
</ng-template>
<ng-template #suffixImageCaptchaButton>
<img src="{{ imageCaptcha }}" (click)="getImageCaptcha()" />
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item>
......
......@@ -135,10 +135,9 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer {
.addPathPatterns("/socialsignon/**")
.addPathPatterns("/authz/credential/**")
.addPathPatterns("/authz/oauth/v20/approval_confirm/**")
.addPathPatterns("/authz/oauth/v20/authorize/approval/**");
.addPathPatterns("/authz/oauth/v20/authorize/approval/**")
.addPathPatterns("/logon/oauth20/bind/**");
;
_logger.debug("add Permission Interceptor");
registry.addInterceptor(historyLogsInterceptor)
......
......@@ -15,7 +15,7 @@
*/
package org.maxkey.web.endpoint;
package org.maxkey.web.contorller;
import java.util.HashMap;
import java.util.regex.Pattern;
......@@ -157,7 +157,11 @@ public class LoginEntryPoint {
if (StringUtils.isNotBlank(authType)){
Authentication authentication = authenticationProvider.authenticate(loginCredential);
if(authentication != null) {
authJwtMessage = new Message<AuthJwt>(authJwtService.genAuthJwt(authentication));
AuthJwt authJwt = authJwtService.genAuthJwt(authentication);
if(WebContext.getAttribute(WebConstants.CURRENT_USER_PASSWORD_SET_TYPE)!=null)
authJwt.setPasswordSetType(
(Integer)WebContext.getAttribute(WebConstants.CURRENT_USER_PASSWORD_SET_TYPE));
authJwtMessage = new Message<AuthJwt>(authJwt);
}
}else {
_logger.error("Login AuthN type must eq normal , tfa or mobile . ");
......
......@@ -15,7 +15,7 @@
*/
package org.maxkey.web.endpoint;
package org.maxkey.web.contorller;
import java.util.Iterator;
import java.util.Set;
......
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -23,13 +23,16 @@ import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.entity.Message;
import org.maxkey.entity.SocialsAssociate;
import org.maxkey.entity.UserInfo;
import org.maxkey.entity.apps.Apps;
import org.maxkey.persistence.service.SocialsAssociatesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
......@@ -52,4 +55,15 @@ public class SocialSignOnListController {
return new Message<List<SocialsAssociate>>(listSocialsAssociate).buildResponse();
}
@ResponseBody
@RequestMapping(value={"/delete"}, produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> delete(@RequestParam("ids") String ids,@CurrentUser UserInfo currentUser) {
_logger.debug("-delete ids : {} " , ids);
if (socialsAssociatesService.deleteBatch(ids)) {
return new Message<Apps>(Message.SUCCESS).buildResponse();
} else {
return new Message<Apps>(Message.FAIL).buildResponse();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册