采用的是springboot+Jwt+shiro,其实也可以采用spring-security-oauth来实现。
有没用到数据库,是在代码中给用户创建的假设的角色和权限
1 JWT工具类:
package com.irootech.bean;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
public class JwtUtil {
/**
* @description :生产token
* @param username : 账户
* @param pwd : 密码
* @return :java.lang.String
*/
public static String createToken(String username, String pwd){
Algorithm algorithm=Algorithm.HMAC256(pwd);
return JWT.create().withClaim("username",username).sign(algorithm);
}
/**
* @description :根据token获取用户名
* @param token :
* @return :java.lang.String
*/
public static String getUsername(String token){
DecodedJWT decodedJWT=JWT.decode(token);
return decodedJWT.getClaim("username").asString();
}
}
2 shiro的配置类:
package com.irootech.config;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* @author anping.tan
* @date 2019/7/26 19:27
*/
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters();
filtersMap.put("jwt", new ShiroFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
Map map=new HashMap();
map.put("/static/**","anon");
map.put("/**","jwt");
map.put("/index","anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
shiroFilterFactoryBean.setUnauthorizedUrl("/403.action");
return shiroFilterFactoryBean;
}
@Bean
public UserInfoRealm userInfoRealm(){
UserInfoRealm userInfoRealm=new UserInfoRealm();
return userInfoRealm;
}
@Bean
public SecurityManager securityManager(UserInfoRealm userInfoRealm){
DefaultSecurityManager defaultSecurityManager=new DefaultWebSecurityManager();
defaultSecurityManager.setRealm(userInfoRealm);
return defaultSecurityManager;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
@Bean(name="simpleMappingExceptionResolver")
public SimpleMappingExceptionResolver
createSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty("UnauthorizedException","403");
r.setExceptionMappings(mappings);
r.setDefaultErrorView("error");
return r;
}
}
3 实现AuthenticationToken 将内容值全部设为token:
package com.irootech.config;
import org.apache.shiro.authc.AuthenticationToken;
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;
}
}
4 定义拦截器:如果不存在Authorization则第一次登陆,直接进去控制器,返回token,下次再请求通过请求头携带着,下次通过入getSubject(request,response).login(jwtToken)进入realm;
package com.irootech.config;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import javax.naming.AuthenticationException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ShiroFilter extends BasicHttpAuthenticationFilter {
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String authorization = req.getHeader("Authorization");
return authorization != null;
}
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest= (HttpServletRequest) request;
String token=httpServletRequest.getHeader("Authorization");
JwtToken jwtToken=new JwtToken(token);
getSubject(request,response).login(jwtToken);
return true;
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginAttempt(request, response)) {
try {
executeLogin(request, response);
} catch (Exception e) {
throw new AuthorizationException("权限不足");
}
}
return true;
}
}
5 实现自定义realm
package com.irootech.config;
import com.irootech.bean.JwtUtil;
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;
public class UserInfoRealm extends AuthorizingRealm {
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username= (String) authenticationToken.getCredentials();
SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(username,username,getName());
return simpleAuthenticationInfo;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
//获取用户名
Object username= JwtUtil.getUsername(principalCollection.toString());
//通过数据库的用户名,查询出用户拥有的角色和权限,假设权限有1,2
simpleAuthorizationInfo.addStringPermission("1");
simpleAuthorizationInfo.addStringPermission("2");
return simpleAuthorizationInfo;
}
}
6 控制层代码:通过加入注解来对接口的权限访问
package com.irootech.controller;
import com.irootech.bean.*;
import com.irootech.service.RolePerssionService;
import com.irootech.service.RoleService;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
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;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
/**
* @author anping.tan
* @date 2019/7/26 17:43
*/
@Controller
public class RoleController {
@RequestMapping("/add.action")
@RequiresPermissions("1")
//跳转到add.html界面
public String add(){
return "add";
}
@RequestMapping("/delete.action")
@RequiresPermissions("3")
//跳转到del.html界面
public String delete(){
return "del";
}
@RequestMapping("/login.action")
@ResponseBody
public String login(HttpServletRequest request,String username,String password){
User user=new User();
user.setUsername("zhangsan");
user.setPassword("a");
String token= JwtUtil.createToken(username,password);
return token;
}
@RequestMapping("/403.action")
//跳转到403界面
public String unfind(){
return "403";
}
@RequestMapping("/update.action")
@RequiresPermissions("2")
//跳转到update.html界面
public String update(){
return "update";
}
}