One 、shiro introduction

Comparison of two frameworks : Security framework Shiro and SpringSecurity Comparison

understand shiro

What is? Shiro

  1. Apache Shiro It's a Java The safety of the ( jurisdiction ) frame .|
  2. Shiro Can finish , authentication , to grant authorization , encryption , session management ,Web Integrate , Cache, etc .

shiro The function of

Authentication: Identity Authentication 、 Sign in , Verify that the user has an identity ;
Authorization: to grant authorization , That is, permission verification , Verify that an authenticated user has certain privileges , That is, judge whether the user can do anything , Such as : Verify that a user has a role , Or fine-grained verification of whether a user has a right to a resource !
Session Manager: session management , That is, after the user logs in, it is the first session , Before I quit , All of its information is in the conversation ; Conversation can be ordinary JavaSE Environmental Science , It can also be Web Environmental Science ;
Cryptography: encryption , Protect data security , Such as password encryption stored in the database , Instead of plaintext storage ;
# ------------------------------------------------------------------------------------
Web Support: Web Support , Can be easily integrated into Web Environmental Science ;
Caching: cache , Like when the user logs in , Its user information , Owned role 、 Permissions don't have to be checked every time , This can improve efficiency
Concurrency: Shiro Support concurrent validation for multi-threaded applications , namely , Such as starting another thread in one thread , It can automatically propagate permissions to the past
Testing: Provide test support ;
Run As: Allows one user to pretend to be another ( If they allow it ) The identity of the access ;
Remember Me: Remember me , This is a very common feature , After one login , You don't have to log in the next time you come

advantage

  • Simple authentication , Support multiple data sources
  • Simple authorization of roles , Support fine-grained authorization ( Method level ) c、 Support level 1 Cache , To improve application performance
  • Apply to Web And non Web Environment e、 Very simple encryption API
  • Not tied to any frame or container , Can run independently

Shiro The architecture of

function describe
Subject user 、 The main body
Securitymanager Manage all users
Authorizer certifier 、 It's an interface
Authorizer Authorized unit 、 Determine the operation authority
Realm Connect data

Be careful :Shiro They don't maintain users 、_ Maintenance access ; We need to design them ourselves / Provide : Then, it is sent to... Through the corresponding interface Sniro that will do

Dependency and configuration

  • rely on
 <!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.7.1</version>
</dependency>
  • Log configuration (log4j)
#Default Shiro Logging
1og4j.1ogger.org.apache.shiro=INFO #Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
1og4j.1ogger.org.apache.shiro.cache.ehcache.EhCache=WARN
  • shiro.ini

    ini The document states

  1. [mian] : Define global variables

    • built-in securityManger object
    • When working with built-in objects , stay [main] What's written in it
[main]
securityManger. attribute = value
# --
user=com.qd.user
securityManger. Object properties =$user
  1. [users] : Define user name and password
[users]
# Define the user name as qd666
qd666 = 123456
# Define the user name as qd666 At the same time admin、role1 Role
qd666 = 123456, admin,role1
  1. [roles] : Define the role
[roles]
role1= Authority Name 1, Authority Name 2
admin= Authority Name 3, Authority Name 4
# --- Query of user table , Add permissions
role1=user:query,user:add
  1. [urls] : Define which built-in urls take effect . stay web Use
[urls]
# url Address = built-in filter Or custom filter
# Appears when accessing /login Of url We must recognize and support authc Corresponding filter
/login=authc
# Any of the url There is no need for authentication and other functions
/**=anon
# All content must ensure that the user has logged in
/**=user
# url abc When accessing, the user must have role1 and role2 Role
/abc=roles["role1,role2"]

Realm structure

Two 、 Function realization

Configure and implement authentication

  1. Authentication

    stay shiro in , Users need to provide principals( identity ) and credentials( prove ) to shiro, So the application can verify the user's identity :

  2. principals

    identity , That is, the identity property of the principal , It could be anything , Such as user name 、 Mailbox, etc , The only can . A body can have more than one principals, But there's only one Primary principals, It's usually a username / password / cell-phone number .

  3. credentials

    prove / By right , Safe values that are known only to the principal , Such as password / Digital certificates are the most common principals and credentials The combination is the user name / It's a password .

The certification process

@Slf4j
public class Certification {
// Create a security manager factory
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// Use the factory to create a security manager
SecurityManager securityManager = factory.getInstance();
// Bind the current security manager to the current thread
SecurityUtils.setSecurityManager(securityManager);
// Get the current user object
Subject currentUser = SecurityUtils.getSubject(); // Get through the current object Session
// Session session = currentUser.getSession();
// session.setAttribute("someKey","aValue");
// String value = (String) session.getAttribute("someKey"); // Judge whether the user has passed the authentication
if(!currentUser.isAuthenticated()) {
// Encapsulate user name and password
AuthenticationToken token = new UsernamePasswordToken("lonestarr", "vespa");
// Set remember me
token.setRememberMe(true);
try {
// authentication
currentUser.login(token); // Performed login
} catch (LockedAccountException lae) { // User lock
log.error(token.getPrincipal() + " is locked");
} catch (AuthenticationException e) {
log.error(" Username or password incorrect ");
}
}
}

Configure and implement authorization

to grant authorization , Also called access control , That is, who can access which resources in the application ― Such as visiting the page / Edit the data / Page operation, etc. ). Several key objects to understand in Authorization : The main body (Subject)、 resources (Resource)、 jurisdiction (Permission) role (Role).

object describe
The main body Users accessing the app
resources Some pages 、 data
jurisdiction Judge whether the user has the right to operate
role Set of authorities

Authorization process

// Connect to certification 
// Print its identification body
log.info("User ["+currentUser.getPrincipal()+"] logged in successfully."); // Role judgment Uniformly return Boolean values
currentUser.hasRole("role1");
List<String> list= Arrays.asList("role1","role2");
// Judge whether the current user owns list All characters in the collection
currentUser.hasAllRoles(list);
//--------------------------------------------------------
// Authority judgment
currentUser.isPermitted("user:query");
// Determine whether you have full permissions
currentUser.isPermitted("user:query","user:add");
//--------------------------------------------------------
// Cancellation
currentUser.logout();
// end
System.exit(0);

The main methods in authentication and Authorization

 // Get the current user object 
Subject currentUser = SecurityUtils.getSubject();
// Get through the current object Session
Session session = currentUser.getSession();
// Determine whether the user is authenticated
currentUser.isAuthenticated()
// Certified
currentUser.getPrincipal()
// Determine whether there is this role
currentUser.hasRole("schwartz")
// Determine whether you have this permission
currentUser.isPermitted("lightsaber:wield")
// Cancellation
currentUser.logout();

Be careful : Shiro By default, the built-in IniRealm,IniRealm from ini Read the user's information in the configuration file , But in development, we need to get data from the database , So we need to customize Realm!

Customize Realm Achieve Authentication

Interface to be inherited

Interface describe
CachingRealm Responsible for cache processing
AuthentictionRealm Responsible for certification
AuthorizingRealm Responsible for authorization

Usually customized realm Inherit AuthonizingRealm

  • shiro Configuration class Fixed steps
@Configuration
public class ShiroConfig {
//1.Realm resources Customize userRealm object
@Bean
public Realm userRealm() { return new UserRealm(); }
//2.securityManager Perform process control
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// relation Realm object
securityManager.setRealm(userRealm);
return securityManager;
}
//3.ShiroFilterFactoryBean Request filter
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// Set up security manager
bean.setSecurityManager(defaultWebSecurityManager);
// Add filter Set default request and other operations
return bean;
}
}

​ stay ShiroConfig Add filter

map Medium key The value is ant route 
** Represents a multi-level path
* Represents a unipolar path
? Represents a character
# -----value Is the default filter -------------
anon : Access without authentication
authc : To access authentication
user : Must have Remember me Function can be used
perms[] : You can access a resource only if you have permission to it
role : You can only access with the permission of a certain role
  • *Realm class Inherit AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
// Authorization method
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println(" Executed the authorization method ");
//....
return null;
} // Certification method
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println(" The authentication method is implemented ");
//......
return null;
}
}

Customize Realm Implement Authorization

  1. For properties on some pages / Component authorization
 have access to session solve 
When you log in, you will currentUser.getPricipal() Put in session in
take currentUser.getPricipal() From MyRealm in doGetAuthenticationinfo The authentication method returns SimpleAuthenticationInfo The first property of the object . Front desk access session Just judge
  1. Control the access rights of the background resource path
  • First visit the page that needs Authorization
// Hard coding , Code redundancy 
@RequestMapping("/xxx")
@ResponseBody
public String unauthorized() {
Subject subject = SecurityUtils.getSubject();
if (subject.isPermitted("vip1")) {
return "ok";
} else {
return " This page cannot be accessed without authorization ";
}
} //----- Method 2
// Set unauthorized requests ( page ) This approach requires adding a large number of filter configurations
bean.setUnauthorizedUrl("/xxx"); //----- Method 3
// annotation as follows
// Hard coding , Code redundancy
@RequiresPermissions("vip1")
@RequestMapping("/xxx")
@ResponseBody
public String unauthorized() {
return "ok";
}
annotation describe
@RequiresAuthentication User login is required
@RequiresGuest Non logged in users can access , You can't access .
@RequiresPermissions Corresponding resource permissions are required
@RequiresRoles You need to have a corresponding role
@RequiresUser You need to complete the user login and complete the remember me function .

tips : When you don't have access , Will throw 500 abnormal AuthorizationException Unified treatment

Simulated Login

Login request It is recommended to define global exception handling

 @RequestMapping("/login")
public String login(String username, String password) {
// Get current certification
Subject subject = SecurityUtils.getSubject();
// Encapsulating user login data
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// Execute login method Fixed code If there are no exceptions, it will succeed
try {
subject.login(token);
return "index";
} catch (AuthenticationException e) { // The username does not exist
model.addAttribute("msg", " Wrong username or password ");
return "login";
}

userRealm

//@Configuration
public class UserRealm extends AuthorizingRealm { // Authorization method
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println(" Executed the authorization method ");
// Get the current user
Subject subject = SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal();
// Definition info, Encapsulate all the roles and permissions of this object
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// Determine whether the login is a super administrator Permissions for all
if (" Super administrator flag ".equals(currentUser.getPermId())){
//1. Get the list of roles and permissions
//2. Binding requires roles and permissions
info.addRole("");
info.addStringPermission("");
}else {
// Administrators
info.addRole("admin");
info.addStringPermission("*.*");
}
return info;
} // Certification method
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println(" The authentication method is implemented ");
// Get the current user
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
// Query the real database
// User user = userService.queryUserByName(userToken.getUsername());
// If the query result is empty , It throws an exception
if (user == null) {
return null;
}
// Password authentication ,shiro Help us automatically match , Then complete the certification
return new SimpleAuthenticationInfo(user, user.getUserPwd(), ""); // resources , password
}
}
        // Set up security manager 
bean.setSecurityManager(defaultWebSecurityManager);
Map<String, String> filterMap = new LinkedHashMap<>();
// Add filter
filterMap.put("/user/addUser", "perms[user:add]");
filterMap.put("/user/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
// Set login request ( page ) Otherwise, an error will be reported
bean.setLoginUrl("/login");
// Set unauthorized requests ( page )
bean.setUnauthorizedUrl("/xxx");
return bean;

tips: The more detailed rules are put in the front !

Log out

 //---- Method 1---- request 
Subject subject = SecurityUtils.getSubject();
subject.logout(); //---- Method 2---- filter
filterMap.put("/user/logout", "logout");

Related articles : Shiro Integrate SpringBoot

3、 ... and 、 Other features

Password encryption

shiro Will get a credentialsMatcher object , To compare passwords . Want to use MD5 Way to encrypt :Md5CredentialsMatcher It's overdue , To use ``HashedCredentialsMatcher` And set the algorithm name .

  1. stay ``securityManager` Set up CredentialsMatcher
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
// Set encryption algorithm
matcher.setHashAlgorithmName("MD5");
// Set the number of encryption
matcher.setHashIterations(2);
userRealm.setCredentialsMatcher(matcher);
  1. Add salt Change the construction method
 return new SimpleAuthenticationInfo(user, ByteSource.Util.bytes(user.getUserPwd()), ByteSource.Util.bytes("12345"),"");
  1. matching
public class PasswordEncoder {
public static String encoder(String password) {
SimpleHash simpleHash = new SimpleHash("MD5", ByteSource.Util.bytes(password), ByteSource.Util.bytes("12345"), 2);
return simpleHash.toString();
}
}

many Realm authentication

Take a chestnut : When logging in to wechat , We can choose to use the mobile phone number 、 You can also select micro signal to log in , So how does this happen ?

  • stay user Add mobile phone number to the table and entity 、 Account number field

  • newly build MobileRealm

@Configuration
public class MobileRealm extends AuthenticatingRealm { @Autowired
UserService userService;
// authentication
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println(" The authentication method is implemented ");
// Get the current user
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
// Query the real database
User user = userService.queryUserByName(userToken.getUsername());
// If the query result is empty , It throws an exception
if (user == null) {
return null;
}
// Password authentication ,shiro Help us automatically match , Then complete the certification
return new SimpleAuthenticationInfo(user, user.getUserPwd(),"");
}
}
  • Set up securityManager
// Related objects 
securityManager.setRealms(Arrays.asList(userRealm,mobileRealm));

At this time, you can log in to your account through your mobile phone number In a multiple Realml In our authentication strategy ,AuthenticationStrategy Interface has three implementation classes , understand

Remember me

  • Generally, the front end will provide the remember me option on the page
  • Realization
 if (subject.isAuthenticated() && subject.isRemembered()) {
subject.login(token);
token.setRememberMe(true);
}
  • Remember that my function corresponds to... By default ``user` filter

  • Set up securityManager

CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
// prevent xss Read cookie
simpleCookie.setHttpOnly(true);
// Remember me cookie entry-into-force time 30 God , Unit second
simpleCookie.setMaxAge(2592000);
rememberMeManager.setCookie(simpleCookie);
securityManager.setRememberMeManager(rememberMeManager);

In microservices and distributed involves cookie Sharing issues Wait, wait, wait ...

Authentication cache

Each time we log in, we can get... From the cache first , If you are not querying from the database , Improve performance

  • stay securityManager Open the cache
// cache 
AbstractCacheManager cacheManager = new MemoryConstrainedCacheManager();
securityManager.setCacheManager(cacheManager);

Remember me , Session management and authentication caching , You can extend the corresponding manager How to interface , Realize your own flexible expansion , For example, share information to redis.

combination Thylemeaf

  1. Import dependence
        <!-- Import shiro And Thymeleaf Integrated package -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
  1. To configure ShiroConfig
    // Integrate ShiroDialect: For integration shiro And thymeleaf
@Bean
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}
  1. Specific use :shiro springsecurity thymeleaf Tag usage and namespace
  2. Notes explain : Annotations use

Four 、 Integrate JWT

thus , Finally, I came to the place I really wanted to write , In actual development , Interface design usually takes into account security and permission design ,JWT Of token The mechanism also does not consume server memory 、 utilize JWT It can also realize single sign on and other functions . Let's simply integrate the use of the two

JSON Web Token(JWT) It's a very light standard . This specification allows us to use JWT Deliver secure information between users and servers . We use a certain amount of coding to generate Token, And in Token Add some non sensitive information to , Pass it on .

When the user logs in successfully, a certificate will be issued to the user token,token from jwt Make . Back up token Before the expiration date , User access depends on token. If token Expired or tampered with , The user is required to log in again . stay token Is valid , All the interfaces that users need permission to access must go through shiro Two core annotations for RequiresRoles as well as RequiresPermissions Validation of the .

  1. Import dependence
        <!-- To configure shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<!-- To configure JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
  1. JWTUtil

    Generate token And verification token Appoint token Expiration time EXPIRE_TIME And the signature key SECRET
public class JwtUtil {
// secret key
private static final String SECRET = "!Q464rwr(&*)6%$#^%&JNJ46da"; /**
* Generate token
* @param map: Information to encrypt
* @return token
*/
public static String sign(Map<String, String> map) {
// Set expiration time Default 3 God
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE, 3);
JWTCreator.Builder builder = JWT.create();
//payload
map.forEach((k, v) -> {
builder.withClaim(k, v);
});
// Specify token expiration time and encryption
String token = builder.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(SECRET));
return token;
} /**
* verification token Legitimacy / obtain token All information
* @param token
* @return verify
*/
public static DecodedJWT verify(String token) {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
} /**
* obtain token Single message
* @param token
* @param s:key
* @return value
*/
public static String getInfo(String token, String s) {
DecodedJWT verify = verify(token);
return verify.getClaim(s).asString();
}
}
  1. JWTFilter

    on top , We use shiro The default privilege block Filter, And because JWT Integration of , We need to customize our own filters JWTFilter
public class JWTFilter extends BasicHttpAuthenticationFilter {
private Logger logger = LoggerFactory.getLogger(this.getClass()); /**
* If a token, On the other hand token Inspection , Otherwise, directly through
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {
// Determine whether the request header is attached "Token"
if (isLoginAttempt(request, response)) {
// If there is , entering executeLogin Method execution login , Check token Whether it is right
try {
executeLogin(request, response);
return true;
} catch (Exception e) {
System.out.println("token error ");
//token error Illegal access
throw new RuntimeException("Unauthorized access!");
// responseError(response, e.getMessage());
}
}
// If the request header does not exist Token, It may be a login operation or a visitor status visit , No need to check token, Go straight back to true
return true;
} /**
* Determine whether the user wants to log in .
* testing header Does it contain Token Field
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String token = req.getHeader("Authorization");
return token != null;
} /**
* Perform the login operation
*/
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("Authorization");
JWTToken jwtToken = new JWTToken(token);
// Submit to realm Log in , If it's wrong, it throws an exception and gets caught
getSubject(request, response).login(jwtToken);
// If no exception is thrown, the login is successful , return true
return true;
} /**
* Support for cross domain
*/
@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"));
// Cross domain will first send a option request , Here we give option Request direct return to normal state
if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpServletResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
} /**
* Jump illegal request to /unauthorized/**
*/
private void responseError(ServletResponse response, String message) {
try {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// Set encoding , Otherwise, Chinese characters will become empty strings during redirection
message = URLEncoder.encode(message, "UTF-8");
httpServletResponse.sendRedirect("/unauthorized/" + message);
} catch (IOException e) {
logger.error(e.getMessage());
}
}
}
  1. JWTToken

    Realization AuthenticationToken Rewrite two methods
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;
}
}
  1. ShiroConfig

    Set the custom Filter, Let the request pass through the filter
@Configuration
public class ShiroConfig {
/**
* Go ahead filter , then filter If a request header is detected token, Then use token Go to login, go Realm To verify
*/
@Bean
public ShiroFilterFactoryBean factory(SecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
// Add your own filter and call it jwt
Map<String, Filter> filterMap = new LinkedHashMap<>();
// Set up our custom JWT filter
filterMap.put("jwt", new JWTFilter());
factoryBean.setFilters(filterMap);
factoryBean.setSecurityManager(securityManager);
// Set the time limit for jump url;
factoryBean.setUnauthorizedUrl("/unauthorized/ No authority ");
Map<String, String> filterRuleMap = new HashMap<>();
// All requests through our own JWT Filter
filterRuleMap.put("/**", "jwt");
// visit /unauthorized/** Not through JWTFilter
filterRuleMap.put("/unauthorized/**", "anon");
factoryBean.setFilterChainDefinitionMap(filterRuleMap);
return factoryBean;
} /**
* Inject securityManager
*/
@Bean
public SecurityManager securityManager(MyRealm myRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// Set customization realm.
securityManager.setRealm(myRealm);
// close shiro Self contained session, See the document for details
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
} /**
* Add annotation support
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
// Compulsory use cglib, Prevent duplicate agents and problems that may cause agent errors
// https://zhuanlan.zhihu.com/p/29161098
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
} @Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
} @Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
  1. Realm class

    Customize our Realm Realize authentication and authorization
@Component
public class MyRealm extends AuthorizingRealm {
private final UserMapper userMapper; @Autowired
public CustomRealm(UserMapper userMapper) {
this.userMapper = userMapper;
} /**
* This method must be overridden , Otherwise, it will report a mistake
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JWTToken;
} /**
* By default, this method is used to verify whether the user name is correct , Just throw an exception .
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("———— Authentication method ————");
String token = (String) authenticationToken.getCredentials();
// Decrypt to obtain username, For comparison with database
String username = JWTUtil.getInfo(token,"username");
if (username == null) {
throw new AuthenticationException("token Authentication failed !");
}
User user = userMapper.queryUserByName(username);
if (user.getPassWord() == null) {
throw new AuthenticationException(" The user does not exist !");
}
return new SimpleAuthenticationInfo(token, token, "MyRealm");
} /**
* This method is called only when the user permission needs to be detected , for example checkRole,checkPermission And so on.
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("———— Permission authentication ————");
String token= principals.toString();
String username = JWTUtil.getInfo(token,"username");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// Get the user role
User user = userMapper.queryUserByName(username);
// Each role has default permissions
int perm = user.getPerm();
// Each user can set new permissions
// String permission = userMapper.getPermission(username);
Set<String> roleSet = new HashSet<>();
Set<String> permissionSet = new HashSet<>();
// Need to put role, permission Package to Set As info.setRoles(), info.setStringPermissions() Parameters of
roleSet.add(perm + "");
// permissionSet.add(rolePermission);
// permissionSet.add(permission);
// Set the roles and permissions that the user has
info.setRoles(roleSet);
info.setStringPermissions(permissionSet);
return info;
}
}
  1. Controller
    @PostMapping("/login")
public ResultMap login(@RequestParam("username") String account,
@RequestParam("password") String password) {
User user = userMapper.queryUserByName(account);
if (user == null || !user.getPassWord().equals(password)) {
throw new RuntimeException(" Wrong user name or password ");
}
Map<String, String> map = new HashMap<>();
map.put("username", user.getAccount());
return R.ok(JwtUtil.sign(map), " Login successful ");
} /**
* Have 1、2、3 Users of the role can access the following page
*/
@GetMapping("/getMessage")
@RequiresRoles(logical = Logical.OR, value = {"1", "2", "3"})
public R getMessage() {
return R.ok("", " Successful access to information ");
}

Running results :



No token In the case of an interview :



Plus the situation :


The End~~

shiro Use and JWT More articles on Integration

  1. SpringBoot2.0+Shiro+JWT Integrate

    SpringBoot2.0+Shiro+JWT Integrate JSON Web Token(JWT) It's a very light standard . This specification allows us to use JWT Deliver secure information between users and servers . We use a certain amount of editing ...

  2. Play from scratch SpringSecurity+JWT Integrated front and rear end separation

    Play from scratch SpringSecurity+JWT Integrated front and rear end separation 2021 year 4 month 9 Japan · Estimated reading time : 50 minute One . What is? Jwt? Json web token (JWT), In order to transmit between network application environments ...

  3. SpringMVC+Apache Shiro+JPA(hibernate) Consolidation configuration

    order : About titles : It's teaching , I really deserve it , But my writing is limited , I really can't find a more reasonable , Humble words express , This is the only way to define . In fact, the most real idea , I just hope this keyword can let more people browse this article , It's also about writing your own articles ...

  4. springboot+shiro+redis( stand-alone redis edition ) Integrate the tutorial - To continue ( Add dynamic role permission control )

    Related courses : 1. springboot+shiro Integrate the tutorial 2. springboot+shiro+redis( stand-alone redis edition ) Integrate the tutorial 3. springboot+shiro+redis( colony re ...

  5. springboot+shiro+redis( stand-alone redis edition ) Integrate the tutorial

    Related courses : 1. springboot+shiro Integrate the tutorial 2. springboot+shiro+redis( colony redis edition ) Integrate the tutorial 3.springboot+shiro+redis( stand-alone red ...

  6. spring boot Shiro JWT Integrate

    One api To support H5, PC and APP Three front ends , If you use session Yes app Not very friendly , and session There are cross domain attacks , So I chose JWT 1. Import dependency package <dependency> ...

  7. springboot2+shiro+jwt Integrate

    Reference resources :https://www.jianshu.com/p/ef0a82d471d2 https://www.jianshu.com/p/3c51832f1051 https://blog.csdn.n ...

  8. SSM+shiro And the integration of related plug-ins maven All dependence , Detailed Notes version , Self use , Continuous updating

    Integrated SSM+shiro frame ,slf4j+logback journal , And some easy to use plug-ins PageHelper,mybatis-generator,Lombok,fastjson wait <?xml versi ...

  9. 1、Shiro Security framework and Spring Integration details

    Apache Shiro It's a security authentication framework , and Spring Security comparison , It's because he uses a relatively simple and easy to understand way of authentication and Authorization . It provides native-session( That is, the authorization information after user authentication is saved in ...

  10. Spring Boot Security JWT Integration to achieve front-end and back-end separation authentication example

    In the previous two chapters, we introduced Spring Boot Security Quick start and Spring Boot JWT Quick start , This section uses JWT and Spring Boot Security A front and back end of the component ...

Random recommendation

  1. 《TypeScript Introduction to Chinese 》 1、 Basic data type

    Reprint :https://github.com/MyErpSoft/TypeScript-Handbook/blob/master/pages/zh-CHS/Basic%20Types.md summary In order to make ...

  2. Do it together webgame,《Javascript snake 》

    2019-09-22 to update : Use canvas Realization :https://github.com/onlyfu/SnakeSir-Javascript The following is a HTML4 Realization : Let's have a little interesting today ,< snake ...

  3. hdu5047 Looking for a regular + Euler formula

    The question : Draw... In a square n individual M, How many planes can be divided at most sol: The first reaction to the problem of how many planes to divide is Euler's formula : Euler's formula in the two-dimensional plane :V+F-E=1 (V:Vertices,F:Faces,E:Ed ...

  4. sell-- wordPOI

    1. http://poi.apache.org/ 2. Create project , The structure is as follows 3、 ... and : See the effect open : Test source : /* ========================================= ...

  5. java Execution procedure

    perform jar java -jar x.jar perform jar It's inside class java -cp x.jar x.x.x

  6. My implementation of AVL tree

    C++ Realized avl Balance tree #include <stdlib.h> #include <time.h> #include <string.h> #include &l ...

  7. sessionstorage,localstorage and cookie The difference between

    sessionStorage and localStorage yes HTML5 Web Storage API Provided , It's convenient in web Save data between requests . With local data , You can avoid data between the browser and the server without having to ...

  8. JavaScript The difference between global and local variables in

    Today I saw an article written by the great God , My understanding of global variables and local variables is still not deep enough , So write this article , Make a conclusion. . Screenshot of great God code + The understanding text is as follows : analysis : In the above code , Variable i yes var command-declared , It works globally , So all ...

  9. Regular expression and Python in re Use of modules

    Regular expression and Python in re Use of modules I've been doing some crawling recently , Regular expressions are used a lot , use Python If you do it, you'll use re modular . This article summarizes regular expressions and re The foundation and use of modules . in addition , Let's introduce an online test program ...

  10. python - Introduction to reptiles Second hand house information of lianjia.com

    import requests from bs4 import BeautifulSoup import sqlite3 conn = sqlite3.connect("test.db&qu ...