优化首页
This commit is contained in:
parent
4516c36b1d
commit
f371c83579
|
|
@ -12,7 +12,7 @@ public class AliyunOSSRest {
|
|||
// @Autowired
|
||||
// private AliyunOSSClient aliyunOSSClient ;
|
||||
@GetMapping("policy.json")
|
||||
public JSONObject getPolicy() {
|
||||
public JSONObject getPolicy(String id) {
|
||||
String dir = String.valueOf(System.currentTimeMillis());
|
||||
// return aliyunOSSClient .getPostObjectPolicy(dir);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ import io.swagger.annotations.ApiOperation;
|
|||
@Api("用户信息管理")
|
||||
@RestController
|
||||
@RequestMapping("/test/*")
|
||||
public class TestController extends BaseController
|
||||
{
|
||||
public class TestController extends BaseController {
|
||||
private final static List<Test> testList = new ArrayList<>();
|
||||
|
||||
{
|
||||
testList.add(new Test("1", "admin", "admin123"));
|
||||
testList.add(new Test("2", "ry", "admin123"));
|
||||
|
|
@ -35,62 +35,52 @@ public class TestController extends BaseController
|
|||
|
||||
@ApiOperation("获取列表")
|
||||
@GetMapping("list")
|
||||
public List<Test> testList()
|
||||
{
|
||||
public List<Test> testList() {
|
||||
return testList;
|
||||
}
|
||||
|
||||
@ApiOperation("新增用户")
|
||||
@PostMapping("save")
|
||||
public AjaxResult save(Test test)
|
||||
{
|
||||
public AjaxResult save(Test test) {
|
||||
return testList.add(test) ? success() : error();
|
||||
}
|
||||
|
||||
@ApiOperation("更新用户")
|
||||
@ApiImplicitParam(name = "Test", value = "单个用户信息", dataType = "Test")
|
||||
@PutMapping("update")
|
||||
public AjaxResult update(Test test)
|
||||
{
|
||||
public AjaxResult update(Test test) {
|
||||
return testList.remove(test) && testList.add(test) ? success() : error();
|
||||
}
|
||||
|
||||
@ApiOperation("删除用户")
|
||||
@ApiImplicitParam(name = "Tests", value = "单个用户信息", dataType = "Test")
|
||||
@DeleteMapping("delete")
|
||||
public AjaxResult delete(Test test)
|
||||
{
|
||||
public AjaxResult delete(Test test) {
|
||||
return testList.remove(test) ? success() : error();
|
||||
}
|
||||
}
|
||||
|
||||
class Test
|
||||
{
|
||||
class Test {
|
||||
private String userId;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public Test()
|
||||
{
|
||||
public Test() {
|
||||
|
||||
}
|
||||
|
||||
public Test(String userId, String username, String password)
|
||||
{
|
||||
public Test(String userId, String username, String password) {
|
||||
this.userId = userId;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
{
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass())
|
||||
{
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -100,41 +90,34 @@ class Test
|
|||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
public int hashCode() {
|
||||
int result = userId != null ? userId.hashCode() : 0;
|
||||
result = 31 * result + (username != null ? username.hashCode() : 0);
|
||||
result = 31 * result + (password != null ? password.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getUserId()
|
||||
{
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId)
|
||||
{
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUsername()
|
||||
{
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username)
|
||||
{
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password)
|
||||
{
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class SwaggerConfig
|
|||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
// 指定当前包路径
|
||||
.apis(RequestHandlerSelectors.basePackage("com.ruoyi.web.controller.tool"))
|
||||
.apis(RequestHandlerSelectors.basePackage("com.ruoyi"))
|
||||
// 扫描所有 .apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
|
|
|
|||
|
|
@ -75,8 +75,10 @@
|
|||
height: 1px;
|
||||
|
||||
}
|
||||
.step-content{
|
||||
margin-top: 20px;
|
||||
}
|
||||
.step-list{
|
||||
display: none;
|
||||
clear: both;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
|
@ -30,7 +30,8 @@ function login() {
|
|||
"rememberMe": rememberMe
|
||||
},
|
||||
success: function(r) {
|
||||
if (r.code == 0) {
|
||||
debugger
|
||||
if (r.code == 200) {
|
||||
location.href = ctx + 'index';
|
||||
} else {
|
||||
$.modal.closeLoading();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.ruoyi.common.base;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
|
|
@ -64,7 +66,7 @@ public class AjaxResult extends HashMap<String, Object>
|
|||
{
|
||||
AjaxResult json = new AjaxResult();
|
||||
json.put("msg", msg);
|
||||
json.put("code", 0);
|
||||
json.put("code", Constants.SUCCESS);
|
||||
return json;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@ public class Constants
|
|||
/**
|
||||
* 通用成功标识
|
||||
*/
|
||||
public static final String SUCCESS = "0";
|
||||
public static final String SUCCESS = "200";
|
||||
|
||||
/**
|
||||
* 通用失败标识
|
||||
*/
|
||||
public static final String FAIL = "1";
|
||||
public static final String FAIL = "500";
|
||||
|
||||
/**
|
||||
* 登录成功
|
||||
|
|
|
|||
|
|
@ -139,6 +139,12 @@
|
|||
<version>3.3.0</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<!--前后端分离验证-->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.5.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 跨域设置
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
private CorsConfiguration buildConfig() {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
// 1允许任何域名使用
|
||||
corsConfiguration.addAllowedOrigin("*");
|
||||
// 2允许任何头
|
||||
corsConfiguration.addAllowedHeader("*");
|
||||
// 3允许任何方法(post、get等)
|
||||
corsConfiguration.addAllowedMethod("*");
|
||||
return corsConfiguration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", buildConfig());
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
|
|
@ -246,6 +246,7 @@ public class ShiroConfig
|
|||
filterChainDefinitionMap.put("/js/**", "anon");
|
||||
filterChainDefinitionMap.put("/ruoyi/**", "anon");
|
||||
filterChainDefinitionMap.put("/druid/**", "anon");
|
||||
filterChainDefinitionMap.put("/api/**", "anon");
|
||||
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
|
||||
// 退出 logout地址,shiro去清除session
|
||||
filterChainDefinitionMap.put("/logout", "logout");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package com.ruoyi.framework.jwt;
|
||||
|
||||
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author Mr.Li
|
||||
* @create 2018-07-12 15:56
|
||||
* @desc
|
||||
**/
|
||||
public class JwtFilter extends BasicHttpAuthenticationFilter {
|
||||
|
||||
|
||||
/**
|
||||
* 执行登录认证
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param mappedValue
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
||||
try {
|
||||
executeLogin(request, response);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
String token = httpServletRequest.getHeader("Authorization");
|
||||
|
||||
JwtToken jwtToken = new JwtToken(token);
|
||||
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
|
||||
getSubject(request, response).login(jwtToken);
|
||||
// 如果没有抛出异常则代表登入成功,返回true
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 对跨域提供支持
|
||||
*/
|
||||
@Override
|
||||
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
||||
httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
|
||||
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
|
||||
httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
|
||||
// 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态
|
||||
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
|
||||
httpServletResponse.setStatus(HttpStatus.OK.value());
|
||||
return false;
|
||||
}
|
||||
return super.preHandle(request, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.ruoyi.framework.jwt;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
|
||||
/**
|
||||
* @author Mr.Li
|
||||
* @create 2018-07-12 15:19
|
||||
* @desc
|
||||
**/
|
||||
public class JwtToken implements AuthenticationToken {
|
||||
|
||||
private String token;
|
||||
|
||||
public JwtToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.ruoyi.framework.jwt;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTDecodeException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.ruoyi.framework.web.util.ServletUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Mr.Li
|
||||
* @create 2018-07-12 14:23
|
||||
* @desc JWT工具类
|
||||
**/
|
||||
public class JwtUtil {
|
||||
|
||||
private static final long EXPIRE_TIME = 5 * 60 * 1000;
|
||||
|
||||
/**
|
||||
* 校验token是否正确
|
||||
*
|
||||
* @param token 密钥
|
||||
* @param secret 用户的密码
|
||||
* @return 是否正确
|
||||
*/
|
||||
public static boolean verify(String token, String username, String secret) {
|
||||
try {
|
||||
//根据密码生成JWT效验器
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
JWTVerifier verifier = JWT.require(algorithm)
|
||||
.withClaim("username", username)
|
||||
.build();
|
||||
//效验TOKEN
|
||||
DecodedJWT jwt = verifier.verify(token);
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得token中的信息无需secret解密也能获得
|
||||
*
|
||||
* @return token中包含的用户名
|
||||
*/
|
||||
public static String getLoginName() {
|
||||
try {
|
||||
String token = ServletUtils.getRequest().getHeader("token");
|
||||
DecodedJWT jwt = JWT.decode(token);
|
||||
return jwt.getClaim("loginName").asString();
|
||||
} catch (JWTDecodeException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名,5min后过期
|
||||
*
|
||||
* @param loginName 用户名
|
||||
* @param secret 用户的密码
|
||||
* @return 加密的token
|
||||
*/
|
||||
public static String sign(String loginName, String secret) {
|
||||
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
// 附带username信息
|
||||
return JWT.create()
|
||||
.withClaim("loginName", loginName)
|
||||
.withExpiresAt(date)
|
||||
.sign(algorithm);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.ruoyi.framework.shiro.realm;
|
|||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ruoyi.framework.jwt.JwtToken;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<if test="status != null and status != ''">
|
||||
AND u.status = #{status}
|
||||
</if>
|
||||
<if test="userType != null and userType != ''">
|
||||
AND u.user_type = #{userType}
|
||||
</if>
|
||||
<if test="phonenumber != null and phonenumber != ''">
|
||||
AND u.phonenumber like concat('%', #{phonenumber}, '%')
|
||||
</if>
|
||||
|
|
|
|||
|
|
@ -22,15 +22,14 @@ import com.ruoyi.common.utils.ExcelUtil;
|
|||
* @author zhujj
|
||||
* @date 2018-11-29
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/agile/genTable")
|
||||
@RestController
|
||||
@RequestMapping("/genTable")
|
||||
public class GenTableController extends BaseController {
|
||||
private String prefix = "agile/genTable";
|
||||
|
||||
@Autowired
|
||||
private IGenTableService genTableService;
|
||||
|
||||
@RequiresPermissions("agile:genTable:view")
|
||||
@GetMapping()
|
||||
public String genTable() {
|
||||
return prefix + "/genTable";
|
||||
|
|
@ -39,7 +38,6 @@ public class GenTableController extends BaseController {
|
|||
/**
|
||||
* 查询代码生成列表
|
||||
*/
|
||||
@RequiresPermissions("agile:genTable:list")
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(GenTable genTable) {
|
||||
|
|
@ -51,7 +49,6 @@ public class GenTableController extends BaseController {
|
|||
/**
|
||||
* 导出代码生成列表
|
||||
*/
|
||||
@RequiresPermissions("agile:genTable:export")
|
||||
@PostMapping("/export")
|
||||
@ResponseBody
|
||||
public AjaxResult export(GenTable genTable) {
|
||||
|
|
@ -71,7 +68,6 @@ public class GenTableController extends BaseController {
|
|||
/**
|
||||
* 新增保存代码生成
|
||||
*/
|
||||
@RequiresPermissions("agile:genTable:add")
|
||||
@Log(title = "代码生成", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@ResponseBody
|
||||
|
|
@ -93,7 +89,6 @@ public class GenTableController extends BaseController {
|
|||
/**
|
||||
* 修改保存代码生成
|
||||
*/
|
||||
@RequiresPermissions("agile:genTable:edit")
|
||||
@Log(title = "代码生成", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@ResponseBody
|
||||
|
|
@ -104,7 +99,6 @@ public class GenTableController extends BaseController {
|
|||
/**
|
||||
* 删除代码生成
|
||||
*/
|
||||
@RequiresPermissions("agile:genTable:remove")
|
||||
@Log(title = "代码生成", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/remove")
|
||||
@ResponseBody
|
||||
|
|
|
|||
|
|
@ -2,46 +2,58 @@
|
|||
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
|
||||
<meta charset="utf-8">
|
||||
<head th:include="include :: header"></head>
|
||||
<link th:href="@{/ajax/libs/layui/extend/steps/steps.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/ajax/libs/layui/css/layui.css}" rel="stylesheet"/>
|
||||
<body class="white-bg">
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
|
||||
<form class="form-horizontal m" id="form-genTable-add">
|
||||
<div id="step_demo" class="step-body">
|
||||
<div class="step-header" style="width:80%;overflow: hidden;">
|
||||
<ul>
|
||||
<li>
|
||||
<span class="step-name">选择表</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="step-name">基本信息</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="step-name">字段信息</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="step-name">生成信息</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="step-name">完成</span>
|
||||
</li>
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 50px;">
|
||||
<legend>基本信息</legend>
|
||||
</fieldset>
|
||||
<form class="form-horizontal m">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">搜索选择框</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="modules" lay-verify="required" lay-search="">
|
||||
<option value="">直接选择或搜索选择</option>
|
||||
<option value="1">layer</option>
|
||||
<option value="2">form</option>
|
||||
<option value="3">layim</option>
|
||||
<option value="4">element</option>
|
||||
<option value="5">laytpl</option>
|
||||
<option value="6">upload</option>
|
||||
<option value="7">laydate</option>
|
||||
<option value="8">laypage</option>
|
||||
<option value="9">flow</option>
|
||||
<option value="10">util</option>
|
||||
<option value="11">code</option>
|
||||
<option value="12">tree</option>
|
||||
<option value="13">layedit</option>
|
||||
<option value="14">nav</option>
|
||||
<option value="15">tab</option>
|
||||
<option value="16">table</option>
|
||||
<option value="17">select</option>
|
||||
<option value="18">checkbox</option>
|
||||
<option value="19">switch</option>
|
||||
<option value="20">radio</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="wrapper wrapper-content animated fadeInRight ibox-content hide">
|
||||
|
||||
<div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this">基本信息</li>
|
||||
<li>字段信息</li>
|
||||
<li>生成信息</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-list">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">数据源名称:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="dataSourceName" name="dataSourceName" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">选择表:</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="tableName" name="tableName" class="form-control" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-list">
|
||||
<div class="layui-tab-content" style="height: 100px;">
|
||||
<form class="form-horizontal m" id="form-genTable-add">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 50px;">
|
||||
<legend>基本信息</legend>
|
||||
</fieldset>
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">实体类名称:</label>
|
||||
<div class="col-sm-8">
|
||||
|
|
@ -73,8 +85,16 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-list">待确认</div>
|
||||
<div class="step-list">
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 50px;">
|
||||
<legend>字段信息</legend>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 50px;">
|
||||
<legend>生成信息</legend>
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">使用的模板:</label>
|
||||
<div class="col-sm-8">
|
||||
|
|
@ -130,14 +150,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<button id="preBtn">上一步</button>
|
||||
<button id="nextBtn">下一步</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div th:include="include::footer"></div>
|
||||
<script th:src="@{/ajax/libs/layui/layui.js}"></script>
|
||||
<script type="text/javascript">
|
||||
var prefix = ctx + "agile/genTable"
|
||||
$("#form-genTable-add").validate({
|
||||
|
|
@ -153,33 +173,48 @@
|
|||
$.operate.save(prefix + "/add", $('#form-genTable-add').serialize());
|
||||
}
|
||||
}
|
||||
layui.config({
|
||||
debug: true
|
||||
,base: '/ajax/libs/layui/extend/'
|
||||
}).extend({
|
||||
steps:"steps/steps"
|
||||
layui.use(['element','form', 'layedit', 'laydate'], function(){
|
||||
var $ = layui.jquery
|
||||
,element = layui.element; //Tab的切换功能,切换事件监听等,需要依赖element模块
|
||||
|
||||
//触发事件
|
||||
var active = {
|
||||
tabAdd: function(){
|
||||
//新增一个Tab项
|
||||
element.tabAdd('demo', {
|
||||
title: '新选项'+ (Math.random()*1000|0) //用于演示
|
||||
,content: '内容'+ (Math.random()*1000|0)
|
||||
,id: new Date().getTime() //实际使用一般是规定好的id,这里以时间戳模拟下
|
||||
})
|
||||
}
|
||||
,tabDelete: function(othis){
|
||||
//删除指定Tab项
|
||||
element.tabDelete('demo', '44'); //删除:“商品管理”
|
||||
|
||||
|
||||
othis.addClass('layui-btn-disabled');
|
||||
}
|
||||
,tabChange: function(){
|
||||
//切换到指定Tab项
|
||||
element.tabChange('demo', '22'); //切换到:用户管理
|
||||
}
|
||||
};
|
||||
|
||||
$('.site-demo-active').on('click', function(){
|
||||
var othis = $(this), type = othis.data('type');
|
||||
active[type] ? active[type].call(this, othis) : '';
|
||||
});
|
||||
|
||||
//Hash地址的定位
|
||||
var layid = location.hash.replace(/^#test=/, '');
|
||||
element.tabChange('test', layid);
|
||||
|
||||
|
||||
layui.use(['jquery', 'steps'],function(){
|
||||
|
||||
var $ = layui.$;
|
||||
|
||||
var $step= $("#step_demo").step();
|
||||
|
||||
$("#preBtn").click(function(event) {
|
||||
console.log("上一步");
|
||||
$step.preStep();//上一步
|
||||
});
|
||||
$("#nextBtn").click(function(event) {
|
||||
console.log("下一步");
|
||||
$step.nextStep();//下一步
|
||||
});
|
||||
$("#goBtn").click(function(event) {
|
||||
$step.goStep(3);//到指定步
|
||||
element.on('tab(test)', function(elem){
|
||||
location.hash = 'test='+ $(this).attr('lay-id');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<head th:include="include :: header"></head>
|
||||
<body class="gray-bg">
|
||||
<div class="container-div">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 search-collapse">
|
||||
<form id="formId">
|
||||
|
|
@ -26,7 +27,7 @@
|
|||
</div>
|
||||
|
||||
<div class="btn-group-sm hidden-xs" id="toolbar" role="group">
|
||||
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="agile:genTable:add">
|
||||
<a class="btn btn-success" onclick="$.operate.addFull()" shiro:hasPermission="agile:genTable:add">
|
||||
<i class="fa fa-plus"></i> 添加
|
||||
</a>
|
||||
<a class="btn btn-primary btn-edit disabled" onclick="$.operate.edit()" shiro:hasPermission="agile:genTable:edit">
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@
|
|||
<artifactId>ruoyi-framework</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.5.19</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
package com.ruoyi.vip.controller;
|
||||
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.json.JSONObject;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.jwt.JwtUtil;
|
||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.framework.web.util.ServletUtils;
|
||||
import com.ruoyi.framework.web.util.ShiroUtils;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.vip.domain.VipUser;
|
||||
import com.ruoyi.vip.service.IVipUserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Api("用户信息管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/vip/user")
|
||||
public class ApiVipUserController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private IVipUserService userService;
|
||||
|
||||
@Autowired
|
||||
private SysPasswordService passwordService;
|
||||
|
||||
@ApiOperation("用户登陆")
|
||||
@Log(title = "用户登陆", businessType = BusinessType.EXPORT)
|
||||
@RequestMapping(value = "/login", method = RequestMethod.POST,produces= "application/json;charset=UTF-8")
|
||||
public AjaxResult login(@RequestBody SysUser user) {
|
||||
AjaxResult success = success("登陆成功");
|
||||
boolean rememberMe=false;
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword(), rememberMe);
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
try
|
||||
{
|
||||
subject.login(token);
|
||||
String tokenSign=JwtUtil.sign(user.getUserName(),user.getUserName());
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.put("token",tokenSign);
|
||||
success.put("data",json);
|
||||
return success;
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
String msg = "用户或密码错误";
|
||||
if (StringUtils.isNotEmpty(e.getMessage()))
|
||||
{
|
||||
msg = e.getMessage();
|
||||
}
|
||||
return error(msg);
|
||||
}
|
||||
}
|
||||
@GetMapping("/info")
|
||||
public AjaxResult get() {
|
||||
AjaxResult success = success("登陆成功");
|
||||
VipUser vipUser = userService.selectUserByLoginName(JwtUtil.getLoginName());
|
||||
success.put("user", vipUser);
|
||||
SysUser vipUser2 =ShiroUtils.getSysUser();
|
||||
return success;
|
||||
}
|
||||
@PostMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo list(VipUser user) {
|
||||
|
||||
List<VipUser> list = userService.selectUserList( user );
|
||||
return getDataTable( list );
|
||||
}
|
||||
|
||||
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
@ResponseBody
|
||||
public AjaxResult export(VipUser user) {
|
||||
List<VipUser> list = userService.selectUserList( user );
|
||||
ExcelUtil<VipUser> util = new ExcelUtil<VipUser>( VipUser.class );
|
||||
return util.exportExcel( list, "user" );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新增保存用户
|
||||
*/
|
||||
@Log(title = "用户管理", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/add")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ResponseBody
|
||||
public AjaxResult addSave(VipUser user) {
|
||||
user.setSalt( ShiroUtils.randomSalt() );
|
||||
user.setPassword( passwordService.encryptPassword( user.getLoginName(), user.getPassword(), user.getSalt() ) );
|
||||
user.setCreateBy( ShiroUtils.getLoginName() );
|
||||
return toAjax( userService.insertUser( user ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 修改保存用户
|
||||
*/
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/edit")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ResponseBody
|
||||
public AjaxResult editSave(VipUser user) {
|
||||
|
||||
user.setUpdateBy( ShiroUtils.getLoginName() );
|
||||
return toAjax( userService.updateUser( user ) );
|
||||
}
|
||||
|
||||
@Log(title = "重置密码", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/resetPwd")
|
||||
@ResponseBody
|
||||
public AjaxResult resetPwdSave(VipUser user) {
|
||||
user.setSalt( ShiroUtils.randomSalt() );
|
||||
user.setPassword( passwordService.encryptPassword( user.getLoginName(), user.getPassword(), user.getSalt() ) );
|
||||
return toAjax( userService.resetUserPwd( user ) );
|
||||
}
|
||||
|
||||
@RequiresPermissions("vip:user:remove")
|
||||
@Log(title = "用户管理", businessType = BusinessType.DELETE)
|
||||
@PostMapping("/remove")
|
||||
@ResponseBody
|
||||
public AjaxResult remove(String ids) {
|
||||
try {
|
||||
return toAjax( userService.deleteUserByIds( ids ) );
|
||||
} catch (Exception e) {
|
||||
return error( e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户名
|
||||
*/
|
||||
@PostMapping("/checkLoginNameUnique")
|
||||
@ResponseBody
|
||||
public String checkLoginNameUnique(VipUser user) {
|
||||
return userService.checkLoginNameUnique( user.getLoginName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验手机号码
|
||||
*/
|
||||
@PostMapping("/checkPhoneUnique")
|
||||
@ResponseBody
|
||||
public String checkPhoneUnique(VipUser user) {
|
||||
return userService.checkPhoneUnique( user );
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验email邮箱
|
||||
*/
|
||||
@PostMapping("/checkEmailUnique")
|
||||
@ResponseBody
|
||||
public String checkEmailUnique(VipUser user) {
|
||||
return userService.checkEmailUnique( user );
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户对象 sys_user
|
||||
* 用户对象 vip_user
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.ruoyi.vip.framework;
|
||||
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
|
||||
/**
|
||||
* 自定义带用户类型token
|
||||
* @author Sunny
|
||||
*/
|
||||
public class UsernamePasswordByUserTypeToken extends UsernamePasswordToken {
|
||||
private static final long serialVersionUID = -7638434498222500528L;
|
||||
|
||||
/*
|
||||
* 用户类型
|
||||
* 1:积分后台用户(后台管理员)
|
||||
* 2:积分兑换端用户(店长店员)
|
||||
* 3:积分验证端用户(第三方合作店铺)
|
||||
*/
|
||||
private String userType;
|
||||
|
||||
public String getUserType() {
|
||||
return userType;
|
||||
}
|
||||
|
||||
public void setUserType(String userType) {
|
||||
this.userType = userType;
|
||||
}
|
||||
|
||||
public UsernamePasswordByUserTypeToken(String username, String password, String userType) {
|
||||
super(username, password);
|
||||
this.userType = userType;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
package com.ruoyi.vip.framework;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.enums.UserStatus;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.framework.web.exception.user.*;
|
||||
import com.ruoyi.framework.web.util.MessageUtils;
|
||||
import com.ruoyi.framework.web.util.ServletUtils;
|
||||
import com.ruoyi.framework.web.util.ShiroUtils;
|
||||
import com.ruoyi.vip.domain.VipUser;
|
||||
import com.ruoyi.vip.service.IVipUserService;
|
||||
import org.apache.shiro.authc.credential.PasswordService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class VipLoginService
|
||||
{
|
||||
@Autowired
|
||||
private VipPasswordService vipPasswordService;
|
||||
|
||||
@Autowired
|
||||
private IVipUserService vipUserService;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
public VipUser login(String username, String password)
|
||||
{
|
||||
// 验证码校验
|
||||
if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
|
||||
throw new CaptchaException();
|
||||
}
|
||||
// 用户名或密码为空 错误
|
||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
// 密码如果不在指定范围内 错误
|
||||
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|
||||
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
|
||||
// 用户名不在指定范围内 错误
|
||||
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|
||||
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
|
||||
// 查询用户信息
|
||||
VipUser user = vipUserService.selectUserByLoginName(username);
|
||||
|
||||
if (user == null && maybeMobilePhoneNumber(username))
|
||||
{
|
||||
user = vipUserService.selectUserByPhoneNumber(username);
|
||||
}
|
||||
|
||||
if (user == null && maybeEmail(username))
|
||||
{
|
||||
user = vipUserService.selectUserByEmail(username);
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
|
||||
throw new UserNotExistsException();
|
||||
}
|
||||
|
||||
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
|
||||
throw new UserDeleteException();
|
||||
}
|
||||
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
|
||||
throw new UserBlockedException(user.getRemark());
|
||||
}
|
||||
|
||||
vipPasswordService.validate(user, password);
|
||||
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
|
||||
recordLoginInfo(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
private boolean maybeEmail(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.EMAIL_PATTERN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean maybeMobilePhoneNumber(String username)
|
||||
{
|
||||
if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*/
|
||||
public void recordLoginInfo(VipUser user)
|
||||
{
|
||||
user.setLoginIp(ShiroUtils.getIp());
|
||||
user.setLoginDate(DateUtils.getNowDate());
|
||||
vipUserService.updateUserInfo(user);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package com.ruoyi.vip.framework;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.framework.web.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.framework.web.exception.user.UserPasswordRetryLimitExceedException;
|
||||
import com.ruoyi.framework.web.util.MessageUtils;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.vip.domain.VipUser;
|
||||
import org.apache.shiro.cache.Cache;
|
||||
import org.apache.shiro.cache.CacheManager;
|
||||
import org.apache.shiro.crypto.hash.Md5Hash;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 登录密码方法
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class VipPasswordService
|
||||
{
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private Cache<String, AtomicInteger> loginRecordCache;
|
||||
|
||||
@Value(value = "${user.password.maxRetryCount}")
|
||||
private String maxRetryCount;
|
||||
|
||||
@PostConstruct
|
||||
public void init()
|
||||
{
|
||||
loginRecordCache = cacheManager.getCache("loginRecordCache");
|
||||
}
|
||||
|
||||
public void validate(VipUser user, String password)
|
||||
{
|
||||
String loginName = user.getLoginName();
|
||||
|
||||
AtomicInteger retryCount = loginRecordCache.get(loginName);
|
||||
|
||||
if (retryCount == null)
|
||||
{
|
||||
retryCount = new AtomicInteger(0);
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
}
|
||||
if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount)));
|
||||
throw new UserPasswordRetryLimitExceedException(Integer.valueOf(maxRetryCount).intValue());
|
||||
}
|
||||
|
||||
if (!matches(user, password))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
||||
loginRecordCache.put(loginName, retryCount);
|
||||
throw new UserPasswordNotMatchException();
|
||||
}
|
||||
else
|
||||
{
|
||||
clearLoginRecordCache(loginName);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matches(VipUser user, String newPassword)
|
||||
{
|
||||
return user.getPassword().equals(encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
}
|
||||
|
||||
public void clearLoginRecordCache(String username)
|
||||
{
|
||||
loginRecordCache.remove(username);
|
||||
}
|
||||
|
||||
public String encryptPassword(String username, String password, String salt)
|
||||
{
|
||||
return new Md5Hash(username + password + salt).toHex().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package com.ruoyi.vip.framework;
|
||||
|
||||
import com.ruoyi.framework.shiro.service.SysLoginService;
|
||||
import com.ruoyi.framework.web.exception.user.*;
|
||||
import com.ruoyi.framework.web.util.ShiroUtils;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysMenuService;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.vip.domain.VipUser;
|
||||
import com.ruoyi.vip.utils.VipUserUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.*;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.realm.AuthorizingRealm;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 自定义Realm 处理登录 权限
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class VipUserRealm extends AuthorizingRealm
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VipUserRealm.class);
|
||||
|
||||
|
||||
@Autowired
|
||||
private VipLoginService vipLoginService;
|
||||
|
||||
/**
|
||||
* 授权
|
||||
*/
|
||||
@Override
|
||||
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
|
||||
{
|
||||
VipUser user = VipUserUtils.getVipUser();
|
||||
// 角色列表
|
||||
Set<String> roles = new HashSet<String>();
|
||||
// 功能列表
|
||||
Set<String> menus = new HashSet<String>();
|
||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录认证
|
||||
*/
|
||||
@Override
|
||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
|
||||
{
|
||||
UsernamePasswordByUserTypeToken upToken = (UsernamePasswordByUserTypeToken) token;
|
||||
String username = upToken.getUsername();
|
||||
String password = "";
|
||||
if (upToken.getPassword() != null)
|
||||
{
|
||||
password = new String(upToken.getPassword());
|
||||
}
|
||||
|
||||
VipUser user = null;
|
||||
try
|
||||
{
|
||||
user = vipLoginService.login(username, password);
|
||||
}
|
||||
catch (CaptchaException e)
|
||||
{
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserNotExistsException e)
|
||||
{
|
||||
throw new UnknownAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserPasswordNotMatchException e)
|
||||
{
|
||||
throw new IncorrectCredentialsException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserPasswordRetryLimitExceedException e)
|
||||
{
|
||||
throw new ExcessiveAttemptsException(e.getMessage(), e);
|
||||
}
|
||||
catch (UserBlockedException e)
|
||||
{
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (RoleBlockedException e)
|
||||
{
|
||||
throw new LockedAccountException(e.getMessage(), e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
|
||||
throw new AuthenticationException(e.getMessage(), e);
|
||||
}
|
||||
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存权限
|
||||
*/
|
||||
public void clearCachedAuthorizationInfo()
|
||||
{
|
||||
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
package com.ruoyi.vip.utils;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||
import com.ruoyi.framework.shiro.realm.UserRealm;
|
||||
import com.ruoyi.vip.domain.VipUser;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
|
||||
import org.apache.shiro.mgt.RealmSecurityManager;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
/**
|
||||
* shiro 工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class VipUserUtils
|
||||
{
|
||||
public static Subject getSubjct()
|
||||
{
|
||||
return SecurityUtils.getSubject();
|
||||
}
|
||||
|
||||
public static Session getSession()
|
||||
{
|
||||
return SecurityUtils.getSubject().getSession();
|
||||
}
|
||||
|
||||
public static void logout()
|
||||
{
|
||||
getSubjct().logout();
|
||||
}
|
||||
|
||||
public static VipUser getVipUser()
|
||||
{
|
||||
VipUser user = null;
|
||||
Object obj = getSubjct().getPrincipal();
|
||||
if (StringUtils.isNotNull(obj))
|
||||
{
|
||||
user = new VipUser();
|
||||
BeanUtils.copyBeanProp(user, obj);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
public static void setVipUser(VipUser user)
|
||||
{
|
||||
Subject subject = getSubjct();
|
||||
PrincipalCollection principalCollection = subject.getPrincipals();
|
||||
String realmName = principalCollection.getRealmNames().iterator().next();
|
||||
PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
|
||||
// 重新加载Principal
|
||||
subject.runAs(newPrincipalCollection);
|
||||
}
|
||||
|
||||
public static void clearCachedAuthorizationInfo()
|
||||
{
|
||||
RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
|
||||
UserRealm realm = (UserRealm) rsm.getRealms().iterator().next();
|
||||
realm.clearCachedAuthorizationInfo();
|
||||
}
|
||||
|
||||
public static Long getUserId()
|
||||
{
|
||||
return getVipUser().getId().longValue();
|
||||
}
|
||||
|
||||
public static String getLoginName()
|
||||
{
|
||||
return getVipUser().getLoginName();
|
||||
}
|
||||
|
||||
public static String getIp()
|
||||
{
|
||||
return getSubjct().getSession().getHost();
|
||||
}
|
||||
|
||||
public static String getSessionId()
|
||||
{
|
||||
return String.valueOf(getSubjct().getSession().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机盐
|
||||
*/
|
||||
public static String randomSalt()
|
||||
{
|
||||
// 一个Byte占两个字节,此处生成的3字节,字符串长度为6
|
||||
SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
|
||||
String hex = secureRandom.nextBytes(3).toHex();
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue